package psn.kiko.service.business.system;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import psn.kiko.constant.DBConstant;
import psn.kiko.constant.MessageConstant;
import psn.kiko.excepion.BaseBusinessException;
import psn.kiko.mapper.business.system.NavigationMapper;
import psn.kiko.pojo.PageResult;
import psn.kiko.pojo.dto.NavigationDTO;
import psn.kiko.pojo.entity.system.NavigationEntity;
import psn.kiko.pojo.vo.DelDetailVO;
import psn.kiko.pojo.vo.LabelValue;
import psn.kiko.pojo.vo.NavigationVO;
import psn.kiko.pojo.vo.SimpleIconFontVO;

import java.util.ArrayList;
import java.util.List;

/**
 * 导航管理服务
 */
@Service
public class NavigationService{
	@Autowired
	NavigationMapper navigationMapper;
	@Autowired
	OperationService operationService;
	@Autowired
	IconFontService iconFontService;
	
	/**
	 * 分页获取导航列表，携带查询条件
	 */
	public PageResult pagingWithCondition(NavigationDTO navigationDTO,int pageNum,int pageSize){
		NavigationEntity navigationEntity = new NavigationEntity();
		BeanUtils.copyProperties(navigationDTO,navigationEntity);
		
		Page<Object> page = PageHelper.startPage(pageNum,pageSize);
		List<NavigationVO> navigationVOList = navigationMapper.selectList(navigationEntity);
		
		PageResult<Object> pageResult = PageResult.builder()
				.total(((int) page.getTotal()))
				.data(navigationVOList).build();
		return pageResult;
	}
	
	/**
	 * 获取导航类型选项
	 */
	public List<LabelValue> getNavTypesWithLabel(){
		return DBConstant.getNavigationTypesWithLabel();
	}
	
	/**
	 * 获取导航状态选项
	 */
	public List<LabelValue> getStatusesWithLabel(){
		return DBConstant.getStatusesWithLabel();
	}
	
	/**
	 * 批量添加导航
	 */
	public Integer addNavigations(List<NavigationDTO> navigationDTOS){
		ArrayList<NavigationEntity> navigationEntities = new ArrayList<>();
		for(NavigationDTO navigationDTO: navigationDTOS){
			//状态须符合定义
			if(!DBConstant.getStatuses().contains(navigationDTO.getEnabled()))
				navigationDTO.setEnabled(DBConstant.DISABLE);
			//导向类型须符合定义
			if(!DBConstant.getNavigationTypes().contains(navigationDTO.getType()))
				navigationDTO.setType(DBConstant.NAVIGATION_ITEM);
			NavigationEntity navigationEntity = new NavigationEntity();
			BeanUtils.copyProperties(navigationDTO,navigationEntity);
			navigationEntities.add(navigationEntity);
		}
		return navigationMapper.insertBatch(navigationEntities);
	}
	
	/**
	 * 根据id批量删除导航
	 */
	@Transactional
	public List<DelDetailVO> deleteNavByIds(List<Integer> navIds){
		//若这批导航中，有的导航已分配了导航项，作为其它导航项的父导航，则拒绝删除其中任何一项
		Integer navGroupCount = navigationMapper.selectCountByParentIds(navIds);
		if(navGroupCount > 0){
			throw new BaseBusinessException(MessageConstant.SOME_NAVIGATION_GROUP_HAS_ALLOCATED_ITEMS);
		}
		//先批量删除中间表中的关联数据
		//删除与这批导航关联的操作（通常是按钮）
		Integer c1 = operationService.batchDeleteWhereNavidsIn(navIds);
		//3、再批量删除导航
		Integer c2 = navigationMapper.deleteBatchByIds(navIds);
		//存储删除详情
		ArrayList<DelDetailVO> delDetailVOS = new ArrayList<>();
		delDetailVOS.add(new DelDetailVO("删除的导航数量",c2));
		delDetailVOS.add(new DelDetailVO("总共删除与这批导航关联的操作的数量",c1));
		return delDetailVOS;
	}
	
	/**
	 * 根据id更新导航
	 */
	public Integer updateNav(NavigationDTO navigationDTO){
		validateDTOData(navigationDTO);
		NavigationEntity navigationEntity = new NavigationEntity();
		BeanUtils.copyProperties(navigationDTO,navigationEntity);
		return navigationMapper.updateById(navigationEntity);
	}
	
	/**
	 * 获取所有导航组选项
	 */
	public List<NavigationVO> getALlNavGroups(){
		NavigationEntity navigationEntity = NavigationEntity.builder().type(DBConstant.NAVIGATION_GROUP).build();
		List<NavigationVO> navigationVOList = navigationMapper.selectList(navigationEntity);
		navigationVOList.forEach(nav->nav.setParentId(null));
		return navigationVOList;
	}
	
	/**
	 * 分页获取导航组的导航项
	 */
	public PageResult<Object> geAllNavItemsOfNavGroup(Integer navGroupId,int pageNUm,int pageSize){
		Page<Object> page = PageHelper.startPage(pageNUm,pageSize);
		NavigationEntity navigationEntity = NavigationEntity.builder().parentId(navGroupId).build();
		List<NavigationVO> navigationVOList = navigationMapper.selectList(navigationEntity);
		PageResult<Object> pageResult = PageResult.builder()
				.total(((int) page.getTotal()))
				.data(navigationVOList)
				.build();
		return pageResult;
	}
	
	/**
	 * 根据id批量启用导航
	 */
	public Integer batchEnableNavByIds(List<Integer> navIds){
		return navigationMapper.updateEnableByIds(navIds,DBConstant.ENABLE);
	}
	
	/**
	 * 根据id批量禁用导航
	 */
	public Integer batchDisableNavByIds(List<Integer> navIds){
		return navigationMapper.updateEnableByIds(navIds,DBConstant.DISABLE);
	}
	
	/**
	 * 添加导航
	 */
	public Integer addNavigation(NavigationDTO navigationDTO){
		//校验导航关键信息合法性，不合法则抛异常，拒绝添加
		validateDTOData(navigationDTO);
		NavigationEntity navigationEntity = new NavigationEntity();
		BeanUtils.copyProperties(navigationDTO,navigationEntity);
		return navigationMapper.insert(navigationEntity);
	}
	
	/**
	 * 校验前端提交的数据
	 */
	private void validateDTOData(NavigationDTO navigationDTO){
		NavigationVO navigationVO = navigationMapper.selectById(navigationDTO.getId());
		//已经被分配的导航项,不能再更改类型为导航组
		if(navigationVO != null
				&&navigationVO.getParentId() != null
				&&navigationVO.getParentId() > 0
				&&navigationDTO.getType() == DBConstant.NAVIGATION_GROUP){
			throw new BaseBusinessException(MessageConstant.ALLOCATED_NAVIGATION_ITEM_CANT_CHANGE_TYPE_AS_GROUP);
		}
		//已含有导航项的导航组,不能再更改类型为导航项
		int itemsCount = navigationMapper.countItemsOfNavGroup(navigationDTO.getId());
		if(itemsCount > 0
				&&navigationDTO.getType() != null
				&&navigationDTO.getType() == DBConstant.NAVIGATION_ITEM
		){
			throw new BaseBusinessException(MessageConstant.CONTAINS_NAVIGATION_ITEMS_CANT_CHANGE_TYPE_AS_ITEM);
		}
		//状态校验
		if(!DBConstant.getStatuses().contains(navigationDTO.getEnabled())){
			navigationDTO.setEnabled(DBConstant.DISABLE);
		}
		//类型校验
		if(!DBConstant.getNavigationTypes().contains(navigationDTO.getType())){
			navigationDTO.setType(DBConstant.NAVIGATION_ITEM);
		}
		//导航项路由校验
		if(navigationDTO.getType() == DBConstant.NAVIGATION_ITEM
				&&!navigationDTO.getRoute().startsWith("/")){
			throw new BaseBusinessException(MessageConstant.NAVIGATION_ITEM_MUST_STARTS_WITH_SLASH);
		}
		//导航组不能再划分到某一导航下
		if(navigationDTO.getType() == DBConstant.NAVIGATION_GROUP
				&&navigationDTO.getParentId() != null
				&&navigationDTO.getParentId() > 0){
			throw new BaseBusinessException(MessageConstant.NAVIGATION_GROUP_SHOULD_NOT_LONG_TO_OTHER_GROUP);
		}
	}
	
	/**
	 * 根据id获取导航
	 * */
	public NavigationVO getNavigationById(Integer navId){
		return navigationMapper.selectById(navId);
	}
	
	/**
	 * 设置导航项为未分配状态
	 */
	public Integer batchRemoveItemsOfNavGroup(List<Integer> navItemIds){
		return navigationMapper.updateParentIdInIds(navItemIds,DBConstant.NAVIGATION_ITEM_UN_ALLOCATED);
	}
	
	/**
	 * 给导航组分配一批导航项
	 */
	public Integer batchAllocateItemsToNavGroup(Integer navGroupId,List<Integer> navItemIds){
		return navigationMapper.updateParentIdInIds(navItemIds,navGroupId);
	}
	
	/**
	 * 启用导航组的一批导航项
	 */
	public Integer batchEnableItemsOfNavGroup(Integer navGroupId,List<Integer> navItemIds){
		return navigationMapper.updateStatusByParentIdAndIds(navGroupId,navItemIds,DBConstant.ENABLE);
	}
	
	/**
	 * 禁用导航组一批导航项
	 */
	public Integer batchDisableItemsOfNavGroup(Integer navGroupId,List<Integer> navItemIds){
		return navigationMapper.updateStatusByParentIdAndIds(navGroupId,navItemIds,DBConstant.DISABLE);
	}
	
	/**
	 * 分页获取未分配的导航项
	 */
	public PageResult<Object> unAllocatedItems(int pageNUm,int pageSize){
		Page<Object> page = PageHelper.startPage(pageNUm,pageSize);
		List<NavigationEntity> navigationEntities = navigationMapper.selectUnAllocatedItems();
		PageResult<Object> pageResult = PageResult.builder()
				.total(((int) page.getTotal()))
				.data(navigationEntities)
				.build();
		return pageResult;
	}
	
	/**
	 * 获取简易字体图标选项
	 */
	public List<SimpleIconFontVO> getIconSelect(){
		return iconFontService.getSimpleIconFont();
	}
	
}
